# coding:UTF-8
import pandas as pd
from pyecharts.charts import Scatter
from pyecharts.charts import Polar
from pyecharts.charts import Map
from pyecharts import options as opts
from pyecharts.commons.utils import JsCode

# 1、数据处理
# 读取数据
df = pd.read_excel('./data/淘宝订单.xlsx')
print(df.head(5))

# 查看数据集大小
print(df.shape)

# 查看索引，数据类型和内存信息
print(df.info())

# 筛选已经完成的订单
print(df[~df['订单付款时间'].isnull()])

# 根据日期，增加星期列
df['星期'] = df['订单创建时间'].dt.dayofweek+1
print(df.head(5))

# 一周每天各个时段订单数量散点图
hours = [
        '0a/12p','1a','2a','3a','4a','5a','6a','7a','8a','9a','10a',
        '11a','12a/0p','1p','2p','3p','4p','5p','6p','7p','8p','9p',
        '10p','11p'
    ]
weeks = ['周一','周二','周三','周四','周五','周六','周日']
# 按星期和小时分组统计订单数量，并转换为dataframe，列名为数量
# to_frame必须保证数据类型正确的前提下才能进行转换，哪怕数据类型错一点，将无法进行转换
# 不能使用reset_index(name='数量')因为这个生成结果集与to_frame保存的结果的样式不一致，这样会导致下面遍历循环的时候，数据集无法进入
week_hour_group = df.groupby([df['星期'],df['订单创建时间'].dt.hour])['订单创建时间'].count().to_frame('数量')
# 将分组后的订单数量列表转换为列表
count_values = week_hour_group['数量'].values.tolist()
# 初始化一个空列表转换为列表
allinfo = []
# 遍历分组后的索引列表，构建包含星期，小时和数量的信息列表
for idx,dt in enumerate(week_hour_group.index.to_list()):
    # 构建包含星期，小时和数量的列表
    info = [dt[0],dt[1],count_values[idx]]
    # 将信息列表添加到allinfo中
    allinfo.append(info)

# 初始化两个空列表，分别用于存储配置和标题配置
single_axis, titles = [],[]
scatter = Scatter(init_opts=opts.InitOpts(width='1000px',height='800px',theme='light',bg_color='#0d735'))
# 遍历倒叙的星期列表（从周日到周一）
for idx ,day in enumerate(weeks[::-1]):
    # 为每个星期添加x轴数据
    scatter.add_xaxis(xaxis_data=hours)
    # 单轴配置 配置单轴的位置，标签间隔，类型等属性
    single_axis.append({
        'left':100, # 设置单轴左边距
        'nameGap':20, # 设置名称与轴线的距离
        'nameLocation':'start', # 设置名称位置在轴线的开始处
        'type':'category', # 设置轴类型
        'boundaryGap':False, # 不显示边界间隔
        'data':hours, # 设置轴上的数据
        'top':'{}%'.format(idx * 100 / 7 + 5), # 设置顶部位置
        'height':'{}%'.format(100 / 7 - 10), # 设置高度
        'gridIndex':idx, # 设置网格索引
        'axisLabel':{'interval':2,'color':'#9FC131'}, # 设置轴标签间隔和颜色
    })
    # 添加标题配置，设置文本，位置和样式
    titles.append(dict(text=day, # 设置标题文本
                       top='{}%'.format(idx * 100 / 7 + 6), # 设置顶部位置
                       left='2%', # 设置左侧位置
                       textStyle=dict(color='#fff211'), # 设置文本样式
                       )) # 设置文本样式
    scatter.add_yaxis(
        '',  # 系列名称为空
        y_axis=[int(item[2]) for item in allinfo if item[0] == 7 - idx], # 根据星期筛选处相应的数量数据（此处警告的原因是数据类型的不确定）
        symbol_size=JsCode('function(p) { return p[1] * 0.15}'), # 动态设置符号大小
        label_opts=opts.LabelOpts(is_show=False), # 不显示数据标签
    )
    # 设置系列的坐标系统为单轴
    scatter.options['series'][idx]['coordinateSystem'] = 'singleAxis'
    # 设置系列对应的单轴索引
    scatter.options['series'][idx]['singleAxisIndex'] = idx

# 多标题配置，将单轴配置列表复制给散点图对象的‘singleAxis’选项
scatter.options['singleAxis'] = single_axis
scatter.set_global_opts(
    xaxis_opts=opts.AxisOpts(is_show=False), # 隐藏x轴
    yaxis_opts=opts.AxisOpts(is_show=False), # 隐藏y轴
    title_opts=titles, # 设置标题选项，这里使用自定义标题列表，会出不符合数据类型的警告
  #  title_opts=opts.TitleOpts(title=titles) # 这样只能支持一个标题的显示，不能支持多个标题的显示
)
scatter.render('1-一周每天各时段订单数量散点图.html')


# 一周各天订单数量极坐标图
week_group = df.groupby(df['星期'])['订单创建时间'].count().to_frame('数量')
print(max(week_group['数量'].values.tolist()))

p = (
    # 初始化极坐标图对象，设置图表数据，高度和背景颜色
    Polar(init_opts=opts.InitOpts(width='1000px',height='800px',bg_color='#0d735'))
    # 添加极坐标图的模式配置
    .add_schema(
        # 设置半径轴选项
        radiusaxis_opts=opts.RadiusAxisOpts(data=weeks, # 设置半径的数据为星期列表
                                            type_='category', # 设置轴类型为类型
                                            axislabel_opts=opts.LabelOpts(font_size=14,color='#00aeff'), # 设置轴标签的字体大小和颜色
                                            axisline_opts=opts.AxisLineOpts(is_show=True, # 显示轴线
                                                                            linestyle_opts=opts.LineStyleOpts(width=2,color='#bee629'))
                                            ),
        # 设置角度轴选项
        angleaxis_opts=opts.AngleAxisOpts(is_clockwise=True, # 设置角度为顺时针方向
                                          max_=5500, # 设置最大值
                                          axislabel_opts=opts.LabelOpts(font_size=14,color='#3be8b1'), # 设置轴标签的字体大小和颜色
                                          axisline_opts=opts.AxisLineOpts(is_show=True, # 显示轴线
                                                                          linestyle_opts=opts.LineStyleOpts(width=2, # 轴线宽度
                                                                                                            type_='dashed', # 轴线样式：仪表盘
                                                                                                            color='#e4e932')), # 轴线颜色
                                          # 设置分割线样式
                                          splitline_opts=opts.SplitLineOpts(is_show=True, # 显示分割线
                                                                            linestyle_opts=opts.LineStyleOpts(type_='dashed',color='#b4da36'), # 设置分割线样式
                                                                            )
                                          )
    )
    # 添加数据系列，使用条形图展示一周各天的订单数量
    .add('',week_group['数量'].values.tolist(),type_='bar')
    # 设置标题选项
    .set_global_opts(
        title_opts=opts.TitleOpts(title='一周各天订单数量分布', # 设置条形图标题
                                  subtitle='', # 副标题
                                  pos_left='center', # 设置标题位置在中心
                                  pos_top='1%', # 设置标题位置在顶部1%处
                                  title_textstyle_opts=opts.TextStyleOpts(color='#fff211',font_size=20) # 设置标题文本样式
                                  ),
        # 设置视觉映射选项
        visualmap_opts=opts.VisualMapOpts(max_=6000, # 设置最大值
                                          is_show=False, # 不显示视觉映射
                                          is_piecewise=True, # 使用分段式视觉映射
                                          split_number=8, # 设置分段数
                                          min_=2500, # 设置最小值
                                          range_color=['#fff7f3','#fde0dd','#fcc5c0','#fa9fb5','#f768a1','#dd3497','#ae017e','#7a0177']) # 设置颜色范围
    )
)
p.render('2-一周各天订单数量极坐标图.html')


# 淘宝订单全国地图分布
# 省份字典
proves = ['上海','云南','内蒙古','北京','台湾','吉林','四川','天津','宁夏','安徽','山东','山西','广东','广西',
         '新疆','江苏','江西','河北','河南','浙江','海南','湖北','湖南','澳门','甘肃','福建','西藏','贵州','辽宁',
         '重庆','陕西','青海','香港','黑龙江']
proves_fin = ['上海市','云南省','内蒙古自治区','北京市','台湾省','吉林省','四川省','天津市','宁夏回族自治区','安徽省',
              '山东省','山西省','广东省','广西壮族自治区','新疆维吾尔自治区','江苏省','江西省','河北省','河南省','浙江省',
              '海南省','湖北省','湖南省','澳门特别行政区','甘肃省','福建省','西藏自治区','贵州省','辽宁省','重庆市',
              '陕西省','青海省','香港特别行政区','黑龙江省']

prov_idc = dict(zip(proves,proves_fin))
df['收货地址'] = df['收货地址'].replace(prov_idc)
area_group = df.groupby(df['收货地址'])['订单创建时间'].count().to_frame('数量')

color_js = """new echarts.graphic.LinearGradient(0,0,1,0
            [{offset : 0,color : '#009ad5'},{offset : 1,color : '#ed1941'}],false)"""

# 初始化地图对象，设置主题，颜色
map_chart = Map(init_opts=opts.InitOpts(theme='dark',width='1000px',height='600px',bg_color='#0d0735'))
# 添加数据系列到地图上
map_chart.add('', # 系列名称
              [list(z) for z in zip(area_group.index.values.tolist(),area_group['数量'].values.tolist())], # 将地区和数量打包成列表
              maptype='china', # 设置地图类型为中国地图
              is_map_symbol_show=False, # 不显示地图上的标记符号
              label_opts=opts.LabelOpts(is_show=True,color='red'), # 显示标签，并设置标签颜色为红色
              itemstyle_opts={
                  'normal':{
                      'shadowColor':'rgba(0,0,0,.5)', # 阴影颜色
                      'shadowBlur':5, # 阴影大小
                      'shadowOffsetY':0, # y轴方向阴影偏移
                      'shadowOffsetX':0, # x轴方向阴影偏移
                      'borderColor':'#fff', # 设置边框颜色
                  }
              }
              )

# 设置全局选项
map_chart.set_global_opts(
    # 设置视觉映射选项
    visualmap_opts=opts.VisualMapOpts(
        is_show=True, # 显示视觉映射
        is_piecewise=True, # 使用分段式视觉映射
        min_=0, # 设置最小值
        max_=3500, # 设置最大值
        split_number=7, # 设置分段数
        series_index=0, # 设置应用视觉映射的数据系列索引
        pos_top='70%', # 设置视觉映射的位置在顶部的70%处
        pos_left='10%', # 设置视觉映射的位置在左侧的10%处
        range_color=['#9ecae1','#6baed6','#4292c6','#2171b5','#08519c','#08316b',
                     '#d4b9da','#c994c7','#df65b9','#e7298a','#ce1256','#981143','#68111f']
    ),
    # 设置提示框选项
    tooltip_opts=opts.TooltipOpts(
        is_show=True, # 显示提示框
        trigger='item', # 提示框触发方式为点击项目
        formatter='{b}:{c}' # 设置提示框内容样式 {b}为区域名，{c}表示数值
    ),
    # 设置标题
    title_opts=opts.TitleOpts(
        title='淘宝taobao订单全国地图分布', # 设置标题名称
        subtitle='', # 设置副标题
        pos_left='5%', # 设置标题位置在顶部的5%处
        title_textstyle_opts=opts.TextStyleOpts(  # 设置标题的样式
            color='#fff211', # 设置标题文字颜色
            font_size=21 # 设置标题文字大小
        )
    )
)
map_chart.render('3-淘宝订单全国分布地图.html')